///
#include "common.hpp"
#include <algorithm>
#include <cstring>

// Thanks planck
bool buffer_is_binary(const unsigned char *data, size_t len) {
  static constexpr size_t mlen = 0x1000;
  auto sz = (std::min)(len, mlen);
  return memchr(data, '\0', sz) != nullptr;
}

namespace gitee {
encoding_t DetectBufferEncoding(const unsigned char *buf, size_t len) {
  if (len == 0) {
    return encoding_t::empty;
  }
  switch (buf[0]) {
  case 0x2B:
    if (len >= 3 && buf[1] == 0x2F && buf[2] == 0xbf) {
      return encoding_t::utf7;
    }
    break;
  case 0xEF:
    if (len >= 3 && buf[1] == 0xbb && buf[2] == 0xbf) {
      return encoding_t::utf8withbom;
    }
    break;
  case 0xFF:
    if (len >= 4 && buf[1] == 0xfe && buf[2] == 0x00 && buf[3] == 0x00) {
      return encoding_t::utf32le;
    }
    if (len >= 2 && buf[1] == 0xfe) {
      return encoding_t::utf16le;
    }
    break;
  case 0xFE:
    if (len >= 2 && buf[1] == 0xff) {
      return encoding_t::utf16be;
    }
    break;
  case 0x00:
    if (len >= 4 && buf[1] == 0x00 && buf[2] == 0xfe && buf[3] == 0xff) {
      return encoding_t::utf32be;
    }
    break;
  default:
    break;
  }
  if (buffer_is_binary(buf, len)) {
    return encoding_t::binary;
  }
  return encoding_t::utf8;
}
} // namespace gitee
